package com.zxxy.search.thread;

import rx.Completable;

import java.util.concurrent.*;

public class ThreadTest {
    public static ExecutorService executor = Executors.newFixedThreadPool(10);
    private static CompletableFuture<String> future01;

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("方法开始---------");
        // 第一种 创建CompletableFuture方式
        /*CompletableFuture.runAsync(()->{
            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果："+i);
        },executor);*/
        System.out.println("方法结束---------");

        // 第二种 创建CompletableFuture方式
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor);*/
        // 得到future后来执行什么可以指定   感知的返回结果   方法完成后的感知
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).whenComplete((res,exception)->{
            // 虽然能得到异常信息，但是没法修改返回数据
            System.out.println("异步任务成功完成！！ 结果是："+res+";异常是："+exception);
        }).exceptionally(throwable -> {
            // 可以感知异常，同事返回默认值
            return 10;
        });*/

        // 方法执行完成后的处理
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).handle((res,thr)->{
            if (res!=null){
                return res * 2;
            }
            if (thr != null){
                return 1;
            }
            return 0;
        });*/


        /**
         * 线程串行化
         *  1）、thenRun：不能获取到上一步的执行结果,无返回值
         *  2）、thenAcceptAsync：能接受上一步结果，但是无返回值
         *  3) 、thenApplyAsync： 能接收上一步返回结果，有返回值
         *
         *
         */

        // 串行化第一种 -》1）
        /*CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenRunAsync(()->{
            System.out.println("任务二启动了。。。。。");
        }, executor);*/
        // 串行化第二种 -》2）
        /*CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenAcceptAsync(res -> {
            System.out.println("任务二启动了。。。。。"+res);
        });*/
        // 串行化第三种 -》3）
        /*CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务二启动了。。。。。" + res);
            return "hello";
        }, executor);*/

        /**
         * 两个任务都要完成
         */

        future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程任务111：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("任务111运行结果：" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务二启动了。。。。。" + res);
            return "hello";
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程任务222：" + Thread.currentThread().getId());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务222运行结果：" );
            return "hello";
        },executor);

        /*future01.runAfterBothAsync(future02,()->{
            System.out.println("任务333开始");
        });*/
        /*future01.thenAcceptBothAsync(future02,(f1,f2)->{
            System.out.println("任务333开始"+f1+"-->"+f2);
        },executor);*/

        /*CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return f1 + "," + f2;
        }, executor);*/


        /**
         * 两个任务只要有一个执行完成，就执行任务3
         * runAfterEitherAsync:不敢知结果，自己也不返回值
         * acceptEitherAsync: 不感知结果，自己没有返回值
         * applyToEitherAsync: 自己感知结果，自己有返回值
         */
        /*future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务3 开始 。。。之前的结果");
        },executor);*/
        /*future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3 开始 。。。之前的结果"+res);
        },executor);*/
        /*CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3 开始 。。。之前的结果" + res);
            return "eee";
        }, executor);*/

        /**
         *
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品图片信息");
            return "hello.jpg";
        },executor);
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品shuxing");
            return "heise 256g";
        },executor);
        CompletableFuture<String> futureDes = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品jieshao");
            return "huawei";
        },executor);
        //CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDes);
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDes);
        anyOf.get();// 等待所有结果执行完
        System.out.println(anyOf.get());

        // System.out.println("方法结束---dierzhong------"+future.get());
    }


    public static void Thread(String[] args) throws ExecutionException, InterruptedException {
        /**
         * 实现线程的方式
         * 1、继承Thread
         * 2、实现Runnable接口
         * 3、实现Callable接口 + futureTask（可以拿到返回值结果，可以处理异常）
         * 4、线程池
         *      给线程池直接提交任务。
         *      我们以后再业务代码中前三种启动线程的方式都不用，将所有的多线程一波任务都交给线程池执行
         *      1、创建
         *          1）、Executors
         *          2）、new ThreadPoolExecutors
         *
         *区别：
         *      第1、2中不能得到返回值，第三种可以获取返回值
         *      第1、2、3都不能控制资源
         *      第4可以控制资源，性能稳定
         *
         */
        FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
        new Thread(futureTask).start();
        // 等待整个线程执行完成，获取返回结果
        Integer integer = futureTask.get();
        System.out.println("放回的结果是："+integer);


        System.out.println("线程池---------------------");
        // 当前系统中线程池只有一两个，每个异步任务，提交给线程池让他自己去执行
        /**
         * 七大参数：
         *
         * corePoolSize: 核心线程数
         * maximumPoolSize:最大线程数量；控制资源
         * keepAliveTime：存活时间，如果当前线程数量大于core数量
         *           释放空闲的线程（maximumPoolSize-corePoolSize），只要线程空闲大于指定的keepAliveTime
         * unit：时间单位
         * BlockingQueue<Runnable> workQueue：阻塞队列，如果任务很多，就会将目前多的任务放在队列里面
         *          只要有线程空闲，就回去队列里面取出新的任务继续执行
         * threadFactory：线程的创建工厂
         * RejectedExecutionHandler handler：如果队列满了，按照我们指定的拒绝策略拒绝执行任务
         *
         *
         * 面试题： 一个线程池 core 7，max 20，queue：50， 100个并发进来怎么分配的？？？
         * 7个会立即得到执行，50个进入队列，再开13个进行执行，剩下的30个就使用拒绝策略
         * 如果不想抛弃还要执行。CallerRunsPolicy、
         *
         *
         *
         * 开发中为什么使用线程池
         * ●降低资源的消耗
         *      ■通过重复利用 已经创建好的线程降低线程的创建和销毁带来的损耗
         * ●提高响应速度
         *      ■因为线程池中 的线程数没有超过线程池的最大上限时，有的线程处于等待分配任务
         *      的状态，当任务来时无需创建新的线程就能执行
         * ●提高线程的可管理性
         *      ■线程池会 根据当前系统特点对池内的线程进行优化处理，减少创建和销毁线程带来
         *      的系统开销。无限的创建和销毁线程不仅消耗系统资源，还降低系统的稳定性，使
         *      用线程池进行统一分配
         *
         *
         *
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(),
                Executors.defaultThreadFactory()
                );


    }

    public static class Thread01 extends Thread {

    }

    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {

            System.out.println("当前线程："+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果："+i);
            return i;
        }
    }
}
